<?php
class MForm extends MHtmlElement {
    const METHOD_GET = 'get';
    const METHOD_POST = 'post';
    const ELEMENT_BUTTON = 'button';
    const ELEMENT_CHECKBOX = 'checkbox';
    const ELEMENT_FILE = 'file';
    const ELEMENT_HIDDEN = 'hidden';
    const ELEMENT_IMAGE = 'image';
    const ELEMENT_LABEL = 'label';
    const ELEMENT_PASSWORD = 'password';
    const ELEMENT_RADIO = 'radio';
    const ELEMENT_RESET = 'reset';
    const ELEMENT_SELECT = 'select';
    const ELEMENT_SUBMIT = 'submit';
    const ELEMENT_TEXT = 'text';
    const ELEMENT_TEXTAREA = 'textarea';
    const ENCTYPE_DEFAULT = 'application/x-www-form-urlencoded';
    const ENCTYPE_DATA = 'multipart/form-data';
    const ENCTYPE_TEXT = 'text/plain';

    const UNIQID = 'mlFormUniqid';

    protected $_title;
    protected $_elements;
    protected $_errors;
    protected $_boundedData;
    protected $_cleanedData;
    protected $_uniqid;
    public $useFormee = true;

    public function __construct($action) {
        $this->_elements = array();
        $this->_errors = array();
        $this->_boundedData = array();
        $this->_cleanedData = array();
        // TODO : Change the way to generate a hash
        $this->_uniqid = MPublisher::hash('mlForm'.$action);

        $this->setId('mlForm'.$this->_uniqid);
        $this->setName('mlForm'.$this->_uniqid);
        $this->setHtmlOption('action', $action);

        $this->add(self::ELEMENT_HIDDEN, self::UNIQID)->setValue($this->_uniqid);
    }

    public function isSubmitted(){
        $data = ($this->getMethod()==self::METHOD_POST)?$_POST:$_GET;
        return (!empty($data[self::UNIQID]) && $data[self::UNIQID]==$this->_uniqid);
    }

    public function isValid(array $data){
        if ($this->isSubmitted()){
            $valid = true;
            foreach($this->_elements as $name=>$element){
                $valid = $element->isValid($data[$name]);
                if ($valid)
                    $this->_cleanedData[$name] = $element->getCleanedValue($data[$name]);
                else
                    return false;
            }
            return $valid;
        }
        return false;
    }

    public function bindData(array $data){
        foreach ($data as $name=>$value){
            $this->_elements[$name]->setValue($value);
        }
        return $this;
    }

    /**
     * @param string $element
     * @param string $name
     * @return MFormElement
     */
    public function add($element, $name){
        $class = 'MForm'.ucfirst($element);
        $object = new $class($name, $this);
        $this->_elements[$name] = $object;
        return $object;
    }

    public function remove($name){
        unset($this->_elements[$name]);
    }

    /**
     * @param array $elements : An array like this array($name=>$element,...)
     * @return MForm
     */
    public function setElements(array $elements){
        foreach ($elements as $name=>$element){
            $this->add($element, $name);
        }
        return $this;
    }

    public function getElement($name){
        return $this->_elements[$name];
    }

    public function renderErrors(){
        $return = '';
        if (!empty($this->_errors)){
            $return .= '<div class="ml-error">'.self::EOL;
            $return .= self::TAB.'<p>'.__t('mandrill.web.form.errors').'</p>'.self::EOL;
            $return .= self::TAB.'<ul>'.self::EOL;
            foreach ($this->_errors as $error){
                $return .= self::TAB.'<li>'.$error.'</li>'.self::EOL;
            }
            $return .= self::TAB.'</ul>'.self::EOL;
            $return .= '</div>'.self::EOL;
        }
        return $return;
    }

    public function addError($error){
        array_push($this->_errors, $error);
    }

    public function getErrors(){
        return $this->_errors;
    }

    public function __toString() {
        if ($this->useFormee){
            __import('formee');
            $this->setHtmlOption('class', 'form '.$this->getHtmlOption('class'));
        }
        $return = '<form'.$this->renderHtmlOptions().'>'.self::EOL;
        if (isset($this->_title)){
            $return .= self::TAB.'<fieldset>'.self::EOL.'<legend>'.$this->_title.'</legend>'.self::EOL;
        }
        foreach ($this->_elements as $element){
            $return .= ($this->useFormee)?'<div class="grid12-12">':'<div>';
            $return .= self::TAB.$element->render().self::EOL;
            $return .= '</div>';
        }
        if (isset($this->_title)){
            $return .= self::TAB.'</fieldset>'.self::EOL;
        }
        $return .= '</form>'.self::EOL;
        return $return;
    }

    public function getTitle() {
        return $this->_title;
    }

    public function setTitle($title) {
        $this->_title = $title;
    }

    public function setAction($action){
        $this->setHtmlOption('action', $action);
    }

    public function getAction(){
        return $this->getHtmlOption('action');
    }

    public function setEnctype($enctype){
        $this->setHtmlOption('enctype', $enctype);
    }

    public function getEnctype(){
        return isset($this->_htmlOptions['enctype'])?$this->_htmlOptions['enctype']:self::ENCTYPE_DEFAULT;
    }

    public function setMethod($method){
        $this->setHtmlOption('method', $method);
    }

    public function getMethod(){
        return isset($this->_htmlOptions['method'])?$this->_htmlOptions['method']:self::METHOD_GET;
    }

    public function setName($name){
        $this->setHtmlOption('name', $name);
    }

    public function getName(){
        return $this->getHtmlOption('name');
    }
}
?>
